﻿using System;
using System.Collections.Generic;
using System.Linq;
using AcademicPlanner.Data;
using AcademicPlanner.Data.Entities;
using AcademicPlanner.Data.Repositories;

namespace AcademicPlanner.Domain.Models.Collections
{
	/// <summary>
	/// AccountCollection represents a collection of <c>Account</c>s.
	/// </summary>
	/// <version>1.0</version>
	/// <since>1.0</since>
	public class AccountCollection : ModelCollection<Account, AccountEntityRepository, AccountEntity>
	{
		/// <summary>
		/// Gets the data layer repository of the underlying <c>AccountEntity</c>s of this collection's <c>Account</c>s.
		/// </summary>
		/// <version>1.0</version>
		/// <since>1.0</since>
		protected override AccountEntityRepository EntityRepo { get { return DomainMaster.DSAS.AccountEntityRepo; } }


		/// <summary>
		/// No argument constructor; invokes the matching base class constructor.
		/// </summary>
		/// <seealso cref="M:AcademicPlanner.Domain.ModelCollection<TModel, TEntityRepo, TREntity>.ModelCollection"/>
		/// <version>1.0</version>
		/// <since>1.0</since>
		public AccountCollection()
			: base()
		{

		}

		/// <summary>
		/// Initializes a AccountCollection with the given <c>AccountEntity</c>s by invoking the matching base class constructor.
		/// </summary>
		/// <param name="pEntities">The list of <c>AccountEntity</c>s underlying this AccountCollection.</param>
		/// <version>1.0</version>
		/// <since>1.0</since>
		public AccountCollection(IList<AccountEntity> pEntities) : base(pEntities)
		{

		}


		/// <summary>
		/// Filters this AccountCollection to return only the <c>Account</c> with a <c>User</c>
		/// having the given username. This method relies on this AccountCollection's 
		/// <see cref="P:EntityRepo"/> to find the matching <c>AccountEntity</c> then creates
		/// the <c>Account</c> represented by that <c>AccountEntity</c>.
		/// </summary>
		/// <param name="pUserName">The username.</param>
		/// <returns>The <c>Account</c> having the given username or <c>null</c>.</returns>
		/// <exception cref="T:AcademicPlanner.Domain.CriticalDomainException">
		/// Thrown with an error code of <c>DomainErrorCode.M_ACCOUNT_ENTITY_RETRIEVAL_BY_USERNAME_FAILURE</c>
		/// when a <see cref="T:AcademicPlanner.Data.DataException"/> occurs;
		/// the <see cref="T:AcademicPlanner.Data.DataException"/> is accessible through the
		/// <c>InnerException</c> property.
		/// </exception>
		/// <seealso cref="P:AcademicPlanner.Domain.DomainMaster.ModelsFountain"/>
		/// <seealso cref="M:AcademicPlanner.Domain.ModelsFountain.GetAccount"/>
		/// <seealso cref="P:EntityRepo"/>
		/// <seealso cref="M:AcademicPlanner.Data.PersonEntityRepository.FindByUserName"/>
		/// <version>1.0</version>
		/// <since>1.0</since>
		public Account WithUserName(string pUserName)
		{
			Account rMod = null;
			AccountEntity vEnt = null;

			try
			{
				vEnt = EntityRepo.FindByUserName(pUserName);
			}
			catch (DataException vDx)
			{
				var vCx = new CriticalDomainException(DomainErrorCode.M_ACCOUNT_ENTITY_RETRIEVAL_BY_USERNAME_FAILURE, vDx);
				throw vCx;
			}

			if (vEnt != null)
				rMod = DomainMaster.ModelsFountain.GetAccount(vEnt);

			return rMod;
		}
	}
}
